/*
 * Copyright (C) 2012 praetorian droid
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.praetoriandroid.arkanoidtest;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.MotionEvent;

public class ArkanoidActivity extends Activity {
    
    public static final int RESULT_WIN  = RESULT_FIRST_USER;
    public static final int RESULT_FAIL = RESULT_FIRST_USER + 1;
    
    private GLView mGLView;
    private SensorManager mSensorManager = null;
    private Sensor accelerometer = null;
    private static Vibrator vibrator;
    private int mResult;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mGLView = new GLView(this);
        mGLView.setKeepScreenOn(true);
        setContentView(mGLView);
        
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        if (mSensorManager != null) accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

        mResult = RESULT_CANCELED;
        
        registerCallback();
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterCallback();
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        mGLView.onResume();
        if (mSensorManager != null && accelerometer != null) {
            mSensorManager.registerListener(accelerometerListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
        }
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        if (mSensorManager != null && accelerometer != null) {
            mSensorManager.unregisterListener(accelerometerListener);
        }
        mGLView.onPause();
    }
    
    private SensorEventListener accelerometerListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {
            float direction = (float) Math.atan2(-event.values[1], -event.values[0]);
            float value = 1;
            mGLView.onAccelerometerEvent(direction, value);
        }
        
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }
    };
    
    /**
     *  Durations for: {platform}, {wall}, {floor} and {brick} collision.
     */
    private static final long vibrateDurations[] = {50, 25, 100, 35};
    
    public void callback(int eventType) {
        if (eventType >= 0 && eventType < vibrateDurations.length) {
            vibrator.vibrate(vibrateDurations[eventType]);
        }
        if (eventType == 2) { // fail
            setResult(RESULT_FAIL);
            finish();
        } else if (eventType == 3) { // win
            setResult(RESULT_WIN);
            finish();
        }
    }
    
    public native void registerCallback();
    public native void unregisterCallback();
    
}

class GLView extends GLSurfaceView {
    
    public GLView(Context context) {
        super(context);
        setRenderer(new NativeGLRenderer());
    }
    
    private float mTilt = (float) Math.PI;
    private float prevX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch(event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            prevX = event.getX();
            break;
        case MotionEvent.ACTION_MOVE:
            mTilt += (float) (event.getX() - prevX) / getWidth();
            prevX = event.getX();
            if (mTilt > Math.PI) mTilt = (float) -Math.PI * 2 + mTilt;
            else if (mTilt < -Math.PI) mTilt = (float) Math.PI * 2 - mTilt;
            nativeOnTiltChanged(mTilt);
            break;
        }
        return true;
    }
    
    @Override
    public void onPause() {
        super.onPause();
        nativeClear();
    }
    
    public void onAccelerometerEvent(float direction, float value) {
        nativeOnTiltChanged(direction);
    }
    
    public native void nativeOnTiltChanged(float tilt);
    public native void nativeClear();
    
}

class NativeGLRenderer implements GLSurfaceView.Renderer {
    
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        nativeSetup(width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        nativeDraw();
    }

    public native void nativeSetup(int width, int height);
    public native void nativeDraw();
    
    static {
        System.loadLibrary("glstuff");
    }
    
}
